{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 车牌识别\n",
    "\n",
    "百度百科：车牌识别技术要求能够将运动中的汽车牌照从复杂背景中提取并识别出来，通过车牌提取、图像预处理、特征提取、车牌字符识别等技术，识别车辆牌号、颜色等信息，目前最新的技术水平为字母和数字的识别率可达到99.7%，汉字的识别率可达到99%。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 开始我们的实验\n",
    "\n",
    "(1)登录百度AI开发平台，选择“文字识别”，使用“创建应用”建立一个车牌识别应用。 获取应用的AppID、API Key、Secret Key，注意:Secret Key要先选择显示，然后复制其现实的字符。\n",
    "\n",
    "例如我创建的文字识别应用获取的AppID、API Key、Secret Key如下：\n",
    "\n",
    "    \"\"\" 公开课版本的限定量文字识别，需要更改为自己的api接口 \"\"\"\n",
    "    pic_APP_ID = '21161335'\n",
    "    pic_API_KEY = 'h45HUETBcSNTHrDldK7wjGL7'\n",
    "    pic_SECRET_KEY = 'GtnhMLMQ8e670ptptAvPzhbCBikwuoOL'\n",
    "\n",
    "(2)熟悉我封装的百度AI图像识别的模块 在代码中输入如下代码，导入我的封装的模块\n",
    "\n",
    "    import sys\n",
    "    sys.path.append('../baidu_api_lib')\n",
    "    from baidu_picture import baidu_picture_2_msg\n",
    "\n",
    "<1>初始化方法，需要传入三个参数，就是上步我们创建“车牌识别”应用获取的三个参数 参数信息如下：\n",
    "\n",
    "    \"\"\" 公开课版本的限定量文字识别，需要更改为自己的api接口 \"\"\"\n",
    "    pic_APP_ID = '21161335'\n",
    "    pic_API_KEY = 'h45HUETBcSNTHrDldK7wjGL7'\n",
    "    pic_SECRET_KEY = 'GtnhMLMQ8e670ptptAvPzhbCBikwuoOL'\n",
    "    \n",
    "调用方式：\n",
    "\n",
    "    # 传入百度AI的参数，进行图像识别\n",
    "    pic_msg = baidu_picture_2_msg(pic_APP_ID, pic_API_KEY, pic_SECRET_KEY)\n",
    "    初始化完毕后，获取pic_msg对象，操作该对象就能进行车牌识别。\n",
    "    \n",
    "<2>车牌识别方法 这是我封装百度车牌识别方法的函数原型：\n",
    "\n",
    "    #从百度AI获取图片分析结果\n",
    "    response = pic_msg.pic_2_msg(baidu_request_url, 'read_word.jpg')\n",
    "    baidu_request_url:百度AI的调用接口，\n",
    "\n",
    "    #百度AI的调用url\n",
    "    baidu_request_url = \"https://aip.baidubce.com/rest/2.0/ocr/v1/license_plate\"\n",
    "\n",
    "    'read_word.jpg':进行车牌识别的图片。\n",
    "    返回值:response为车牌识别的信息\n",
    "    response.json()['words_result']['number']:识别车牌\n",
    "\n",
    "    response.json()还有不少参数，通过print(response.json())可以发现"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "######################################################\n",
    "#\n",
    "# 先感受下小派认识车牌,选择本cell，按shirt+enter键运行本模块\n",
    "#\n",
    "######################################################\n",
    "#!/usr/bin/env python\n",
    "# -*- coding: utf-8 -*-\n",
    "#\n",
    "# Copyright (c) 2020 Taste all Pi.\n",
    "#\n",
    "# Licensed under the GNU General Public License, Version 2.0 (the \"License\");\n",
    "# you may not use this file except in compliance with the License.\n",
    "# You may obtain a copy of the License at\n",
    "#\n",
    "#   http://www.gnu.org/licenses/gpl-2.0.html\n",
    "#\n",
    "# Unless required by applicable law or agreed to in writing, software\n",
    "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
    "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
    "# See the License for the specific language governing permissions and\n",
    "# limitations under the License.\n",
    "\n",
    "#导入标准库\n",
    "import sys\n",
    "import os\n",
    "from playsound import playsound\n",
    "import cv2 as cv\n",
    "import time\n",
    "from multiprocessing import Process, Queue\n",
    "import multiprocessing\n",
    "\n",
    "#导入自定义库\n",
    "sys.path.append('../baidu_api_lib')\n",
    "from baidu_picture import baidu_picture_2_msg\n",
    "from baidu_sound import baidu_word_2_sound\n",
    "\n",
    "\"\"\" 公开课版本的限定量文字识别，需要更改为自己的api接口 \"\"\"\n",
    "pic_APP_ID = '21161335'\n",
    "pic_API_KEY = 'h45HUETBcSNTHrDldK7wjGL7'\n",
    "pic_SECRET_KEY = 'GtnhMLMQ8e670ptptAvPzhbCBikwuoOL'\n",
    "\n",
    "#百度AI的调用url\n",
    "baidu_request_url = \"https://aip.baidubce.com/rest/2.0/ocr/v1/license_plate\"\n",
    "\n",
    "#　获取摄像头图像\n",
    "def camera_frame_func(task_name, mult_queue1, mydict):\n",
    "    \n",
    "    # 创建一个VideoCapture对象\n",
    "    capture = cv.VideoCapture(0) \n",
    "    \n",
    "    #更新人脸识别信息\n",
    "    mydict[\"get_pic\"] = \"false\"\n",
    "    \n",
    "    #　给出提示信息\n",
    "    print(task_name + \"任务启动\")\n",
    "    \n",
    "    try:\n",
    "        while True:\n",
    "            # 一帧一帧读取视频\n",
    "            ret, frame = capture.read()\n",
    "            \n",
    "            #将拍摄到的图片发送到消息队列中\n",
    "            if mydict[\"get_pic\"] == \"true\":\n",
    "                mydict[\"get_pic\"] = \"false\"\n",
    "                mult_queue1.put(frame)\n",
    "\n",
    "            # 本地显示视频图像\n",
    "            cv.imshow('real_time picture', frame) \n",
    "            cv.waitKey(1)\n",
    "\n",
    "    except KeyboardInterrupt:\n",
    "        # 释放cap,销毁窗口\n",
    "        capture.release()    \n",
    "        #关闭显示窗口\n",
    "        cv.destroyAllWindows() \n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "#处理图像\n",
    "def proc_frame_func(task_name, mult_queue, mydict):\n",
    "    #　给出提示信息\n",
    "    print(task_name + \"任务启动\")\n",
    "    \n",
    "    # 传入百度AI的参数，进行图像识别\n",
    "    pic_msg = baidu_picture_2_msg(pic_APP_ID, pic_API_KEY, pic_SECRET_KEY)\n",
    "    \n",
    "    #传入百度AI的参数，进行语音合成\n",
    "    word_2_sound = baidu_word_2_sound(pic_APP_ID, pic_API_KEY, pic_SECRET_KEY)\n",
    "    word_2_sound.trans_word_to_sound(\"欢迎使用智能停车厂系统\",'tst_sound.mp3')\n",
    "    os.system('mplayer ' + 'tst_sound.mp3')\n",
    "    time.sleep(2)\n",
    "    \n",
    "    try:\n",
    "        while True:\n",
    "            #从队列中获取图片，显示图像质量\n",
    "            mydict[\"get_pic\"] = \"true\"\n",
    "            frame = mult_queue.get()\n",
    "            cv.waitKey(1)           \n",
    "\n",
    "            # 写入图片\n",
    "            cv.imwrite('read_word.jpg',frame)\n",
    "            \n",
    "            #从百度AI获取图片分析结果\n",
    "            response = pic_msg.pic_2_msg(baidu_request_url, 'read_word.jpg')\n",
    "            \n",
    "            #给出百度AI分析的数据\n",
    "            #print(response.json())\n",
    "            \n",
    "            #识别出正确的车牌\n",
    "            if 'words_result' in response.json():\n",
    "                #识别出正确的车牌\n",
    "                card_num = response.json()['words_result']['number']\n",
    "                print(card_num)  \n",
    "                \n",
    "                #播报欢迎词\n",
    "                word_2_sound.trans_word_to_sound(\"欢迎\"+card_num+\"入场\",'tst_sound.mp3')\n",
    "                os.system('mplayer ' + 'tst_sound.mp3')\n",
    "              \n",
    "            time.sleep(2)\n",
    "            \n",
    "    except KeyboardInterrupt:\n",
    "        os.remove('tst_sound.mp3')\n",
    "        os.remove('read_word.jpg')\n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "if __name__ == \"__main__\":\n",
    "    try:\n",
    "        \n",
    "        mydict=multiprocessing.Manager().dict()\n",
    "        \n",
    "        #　定义传递图像队列和传递图像处理结果队列\n",
    "        q_frame = Queue()\n",
    "        \n",
    "        #　采集摄像头进程、处理图片进程、播报语音信息\n",
    "        get_camera_frame = Process(target=camera_frame_func, args=(\"获取摄像头图像\", q_frame, mydict))\n",
    "        proc_frame       = Process(target=proc_frame_func, args=(\"处理图像\", q_frame, mydict))\n",
    "        \n",
    "        # 启动任务\n",
    "        get_camera_frame.start()\n",
    "        proc_frame.start()\n",
    "\n",
    "    except KeyboardInterrupt:\n",
    "        print(\"任务被终止了\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 让我们临摹代码，学习“车牌识别”功能"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# #导入标准库\n",
    "# import sys\n",
    "\n",
    "# import os\n",
    "\n",
    "# from playsound import playsound\n",
    "\n",
    "# import cv2 as cv\n",
    "\n",
    "# import time\n",
    "\n",
    "# from multiprocessing import Process, Queue\n",
    "\n",
    "# import multiprocessing\n",
    "\n",
    "\n",
    "# #导入自定义库\n",
    "# sys.path.append('../baidu_api_lib')\n",
    "\n",
    "# from baidu_picture import baidu_picture_2_msg\n",
    "\n",
    "# from baidu_sound import baidu_word_2_sound\n",
    "\n",
    "# \"\"\" 公开课版本的限定量文字识别，需要更改为自己的api接口 \"\"\"\n",
    "# pic_APP_ID = '21161335'\n",
    "\n",
    "# pic_API_KEY = 'h45HUETBcSNTHrDldK7wjGL7'\n",
    "\n",
    "# pic_SECRET_KEY = 'GtnhMLMQ8e670ptptAvPzhbCBikwuoOL'\n",
    "\n",
    "\n",
    "# #百度AI的调用url\n",
    "# baidu_request_url = \"https://aip.baidubce.com/rest/2.0/ocr/v1/license_plate\"\n",
    "\n",
    "\n",
    "# #　获取摄像头图像\n",
    "# def camera_frame_func(task_name, mult_queue1, mydict):\n",
    "\n",
    "    \n",
    "#     # 创建一个VideoCapture对象\n",
    "#     capture = cv.VideoCapture(0) \n",
    "\n",
    "    \n",
    "#     #更新人脸识别信息\n",
    "#     mydict[\"get_pic\"] = \"false\"\n",
    "\n",
    "    \n",
    "#     #　给出提示信息\n",
    "#     print(task_name + \"任务启动\")\n",
    "\n",
    "    \n",
    "#     try:\n",
    "\n",
    "#         while True:\n",
    "\n",
    "#             # 一帧一帧读取视频\n",
    "#             ret, frame = capture.read()\n",
    "\n",
    "            \n",
    "#             #将拍摄到的图片发送到消息队列中\n",
    "#             if mydict[\"get_pic\"] == \"true\":\n",
    "\n",
    "#                 mydict[\"get_pic\"] = \"false\"\n",
    "\n",
    "#                 mult_queue1.put(frame)\n",
    "\n",
    "\n",
    "#             # 本地显示视频图像\n",
    "#             cv.imshow('real_time picture', frame) \n",
    "\n",
    "#             cv.waitKey(1)\n",
    "\n",
    "\n",
    "#     except KeyboardInterrupt:\n",
    "\n",
    "#         # 释放cap,销毁窗口\n",
    "#         capture.release()    \n",
    "\n",
    "#         #关闭显示窗口\n",
    "#         cv.destroyAllWindows() \n",
    "\n",
    "#         print(task_name + \"任务被终止\")\n",
    "\n",
    "        \n",
    "# #处理图像\n",
    "# def proc_frame_func(task_name, mult_queue, mydict):\n",
    "\n",
    "#     #　给出提示信息\n",
    "#     print(task_name + \"任务启动\")\n",
    "\n",
    "    \n",
    "#     # 传入百度AI的参数，进行图像识别\n",
    "#     pic_msg = baidu_picture_2_msg(pic_APP_ID, pic_API_KEY, pic_SECRET_KEY)\n",
    "\n",
    "    \n",
    "#     #传入百度AI的参数，进行语音合成\n",
    "#     word_2_sound = baidu_word_2_sound(APP_ID, API_KEY, SECRET_KEY)\n",
    "\n",
    "#     word_2_sound.trans_word_to_sound(\"欢迎使用智能停车厂系统\",'tst_sound.mp3')\n",
    "\n",
    "#     os.system('mplayer ' + 'tst_sound.mp3')\n",
    "\n",
    "#     time.sleep(2)\n",
    "\n",
    "    \n",
    "#     try:\n",
    "\n",
    "#         while True:\n",
    "\n",
    "#             #从队列中获取图片，显示图像质量\n",
    "#             mydict[\"get_pic\"] = \"true\"\n",
    "\n",
    "#             frame = mult_queue.get()\n",
    "\n",
    "#             cv.waitKey(1)           \n",
    "\n",
    "\n",
    "#             # 写入图片\n",
    "#             cv.imwrite('read_word.jpg',frame)\n",
    "\n",
    "            \n",
    "#             #从百度AI获取图片分析结果\n",
    "#             response = pic_msg.pic_2_msg(baidu_request_url, 'read_word.jpg')\n",
    "\n",
    "            \n",
    "#             #给出百度AI分析的数据\n",
    "#             #print(response.json())\n",
    "\n",
    "            \n",
    "#             #识别出正确的车牌\n",
    "#             if 'words_result' in response.json():\n",
    "\n",
    "#                 #识别出正确的车牌\n",
    "#                 card_num = response.json()['words_result']['number']\n",
    "\n",
    "#                 print(card_num)  \n",
    "\n",
    "                \n",
    "#                 #播报欢迎词\n",
    "#                 word_2_sound.trans_word_to_sound(\"欢迎\"+card_num+\"入场\",'tst_sound.mp3')\n",
    "\n",
    "#                 os.system('mplayer ' + 'tst_sound.mp3')\n",
    "\n",
    "              \n",
    "#             time.sleep(2)\n",
    "\n",
    "            \n",
    "#     except KeyboardInterrupt:\n",
    "\n",
    "#         os.remove('tst_sound.mp3')\n",
    "\n",
    "#         os.remove('read_word.jpg')\n",
    "\n",
    "#         print(task_name + \"任务被终止\")\n",
    "\n",
    "        \n",
    "# if __name__ == \"__main__\":\n",
    "\n",
    "#     try:\n",
    "\n",
    "        \n",
    "#         mydict=multiprocessing.Manager().dict()\n",
    "\n",
    "        \n",
    "#         #　定义传递图像队列和传递图像处理结果队列\n",
    "#         q_frame = Queue()\n",
    "\n",
    "        \n",
    "#         #　采集摄像头进程、处理图片进程、播报语音信息\n",
    "#         get_camera_frame = Process(target=camera_frame_func, args=(\"获取摄像头图像\", q_frame, mydict))\n",
    "\n",
    "#         proc_frame       = Process(target=proc_frame_func, args=(\"处理图像\", q_frame, mydict))\n",
    "\n",
    "        \n",
    "#         # 启动任务\n",
    "#         get_camera_frame.start()\n",
    "\n",
    "#         proc_frame.start()\n",
    "\n",
    "\n",
    "#     except KeyboardInterrupt:\n",
    "\n",
    "#         print(\"任务被终止了\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 课后练习\n",
    "\n",
    "1、我们的智能停车场只能记住进入停车厂的车牌号，我们需要车辆进入后，再出停车场后，播报停车时间。\n",
    "2、可以自行添加计费功能，报告停车时间和停车费用。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#导入标准库\n",
    "import sys\n",
    "import os\n",
    "from playsound import playsound\n",
    "import cv2 as cv\n",
    "import time\n",
    "from multiprocessing import Process, Queue\n",
    "import multiprocessing\n",
    "from datetime import datetime\n",
    "\n",
    "#导入自定义库\n",
    "sys.path.append('../baidu_api_lib')\n",
    "from baidu_picture import baidu_picture_2_msg\n",
    "from baidu_sound import baidu_word_2_sound\n",
    "\n",
    "\"\"\" 公开课版本的限定量文字识别，需要更改为自己的api接口 \"\"\"\n",
    "pic_APP_ID = '21161335'\n",
    "pic_API_KEY = 'h45HUETBcSNTHrDldK7wjGL7'\n",
    "pic_SECRET_KEY = 'GtnhMLMQ8e670ptptAvPzhbCBikwuoOL'\n",
    "\n",
    "#百度AI的调用url\n",
    "baidu_request_url = \"https://aip.baidubce.com/rest/2.0/ocr/v1/license_plate\"\n",
    "\n",
    "#　获取摄像头图像\n",
    "def camera_frame_func(task_name, mult_queue1, mydict):\n",
    "    \n",
    "    # 创建一个VideoCapture对象\n",
    "    capture = cv.VideoCapture(0) \n",
    "    \n",
    "    #更新人脸识别信息\n",
    "    mydict[\"get_pic\"] = \"false\"\n",
    "    \n",
    "    #　给出提示信息\n",
    "    print(task_name + \"任务启动\")\n",
    "    \n",
    "    try:\n",
    "        while True:\n",
    "            # 一帧一帧读取视频\n",
    "            ret, frame = capture.read()\n",
    "            \n",
    "            #将拍摄到的图片发送到消息队列中\n",
    "            if mydict[\"get_pic\"] == \"true\":\n",
    "                mydict[\"get_pic\"] = \"false\"\n",
    "                mult_queue1.put(frame)\n",
    "\n",
    "            # 本地显示视频图像\n",
    "            cv.imshow('real_time picture', frame) \n",
    "            cv.waitKey(1)\n",
    "\n",
    "    except KeyboardInterrupt:\n",
    "        # 释放cap,销毁窗口\n",
    "        capture.release()    \n",
    "        #关闭显示窗口\n",
    "        cv.destroyAllWindows() \n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "#处理图像\n",
    "def proc_frame_func(task_name, mult_queue, mydict):\n",
    "    #　给出提示信息\n",
    "    print(task_name + \"任务启动\")\n",
    "    \n",
    "    # 传入百度AI的参数，进行图像识别\n",
    "    pic_msg = baidu_picture_2_msg(pic_APP_ID, pic_API_KEY, pic_SECRET_KEY)\n",
    "    \n",
    "    #传入百度AI的参数，进行语音合成\n",
    "    word_2_sound = baidu_word_2_sound(pic_APP_ID, pic_API_KEY, pic_SECRET_KEY)\n",
    "    word_2_sound.trans_word_to_sound(\"欢迎使用智能停车厂系统\",'tst_sound.mp3')\n",
    "    os.system('mplayer ' + 'tst_sound.mp3')\n",
    "    time.sleep(2)\n",
    "    \n",
    "    #定义一个空字典\n",
    "    parking_car = {}\n",
    "    \n",
    "    try:\n",
    "        while True:\n",
    "            #从队列中获取图片，显示图像质量\n",
    "            mydict[\"get_pic\"] = \"true\"\n",
    "            frame = mult_queue.get()\n",
    "            cv.waitKey(1)           \n",
    "\n",
    "            # 写入图片\n",
    "            cv.imwrite('read_word.jpg',frame)\n",
    "            \n",
    "            #从百度AI获取图片分析结果\n",
    "            response = pic_msg.pic_2_msg(baidu_request_url, 'read_word.jpg')\n",
    "            \n",
    "            #给出百度AI分析的数据\n",
    "            #print(response.json())\n",
    "            \n",
    "            #识别出正确的车牌\n",
    "            if 'words_result' in response.json():\n",
    "                #识别出正确的车牌\n",
    "                card_num = response.json()['words_result']['number']\n",
    "                #print(card_num)  \n",
    "                \n",
    "                #如果车已经进入停车场，则获取进场时间\n",
    "                if card_num in parking_car.keys():\n",
    "                    #获取进入停车场、离开停车场时间，并计算停车时间\n",
    "                    in_parking_time = parking_car.pop(card_num)\n",
    "                    out_parking_time = datetime.now()\n",
    "                    \n",
    "                    #当前计算停车时间以秒为单位，可以更改为以分钟或小时为单位\n",
    "                    parking_time = (out_parking_time - in_parking_time).seconds\n",
    "                    \n",
    "                    #根据停车分钟数，可以添加自己的计费程序\n",
    "                    \n",
    "                    #播报欢迎词\n",
    "                    word_2_sound.trans_word_to_sound(card_num+\"停车\"+str(parking_time)+\"秒，一路顺风\",'tst_sound.mp3')\n",
    "                    os.system('mplayer ' + 'tst_sound.mp3')\n",
    "                \n",
    "                    #print(in_parking_time)\n",
    "                    #print(out_parking_time)\n",
    "                    #print(parking_time)\n",
    "                #该车没有进入，则记录进场时间    \n",
    "                else:\n",
    "                    #将进场时间记录到停车场系统中\n",
    "                    parking_car[card_num] = datetime.now()\n",
    "                    #print(parking_car)\n",
    "\n",
    "                    #播报欢迎词\n",
    "                    word_2_sound.trans_word_to_sound(\"欢迎\"+card_num+\"入场\",'tst_sound.mp3')\n",
    "                    os.system('mplayer ' + 'tst_sound.mp3')\n",
    "              \n",
    "            time.sleep(5)\n",
    "            \n",
    "    except KeyboardInterrupt:\n",
    "        os.remove('tst_sound.mp3')\n",
    "        os.remove('read_word.jpg')\n",
    "        print(task_name + \"任务被终止\")\n",
    "        \n",
    "if __name__ == \"__main__\":\n",
    "    try:\n",
    "        \n",
    "        mydict=multiprocessing.Manager().dict()\n",
    "        \n",
    "        #　定义传递图像队列和传递图像处理结果队列\n",
    "        q_frame = Queue()\n",
    "        \n",
    "        #　采集摄像头进程、处理图片进程、播报语音信息\n",
    "        get_camera_frame = Process(target=camera_frame_func, args=(\"获取摄像头图像\", q_frame, mydict))\n",
    "        proc_frame       = Process(target=proc_frame_func, args=(\"处理图像\", q_frame, mydict))\n",
    "        \n",
    "        # 启动任务\n",
    "        get_camera_frame.start()\n",
    "        proc_frame.start()\n",
    "\n",
    "    except KeyboardInterrupt:\n",
    "        print(\"任务被终止了\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
